﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using StackExchange.Redis;

namespace utils
{
    public class RedisUtil
    {

        private static readonly object _lock = new object();

        private ConnectionMultiplexer redisMultiplexer;

        private readonly IConfiguration _configuration;

        IServer redisServer;
        IDatabase db = null;

        public RedisUtil(IConfiguration configuration)
        {
            _configuration = configuration;
            var redisConnection = _configuration["RedisConnectionString"];
            redisMultiplexer = ConnectionMultiplexer.Connect(redisConnection);
            db = redisMultiplexer.GetDatabase();
            redisServer = redisMultiplexer.GetServer(redisMultiplexer.GetEndPoints()[0]);
        }

        public ISubscriber getSubscriber()
        {
            return this.redisMultiplexer.GetSubscriber();
        }

        /// <summary>
        /// 获取匹配的Key
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public string[] Keys(string pattern)
        {
            var _kyes = redisServer.Keys(database: this.db.Database, pattern: pattern);
            return _kyes.Select(x => x.ToString()).ToArray();
        }


        //添加一个key 或者覆盖key的值
        public async Task<bool> SetKey(string key, string value)
        {
            return await db.StringSetAsync(key, value, null, false, StackExchange.Redis.When.Always);
        }


        //添加一个key 或者覆盖key的值
        public async Task<bool> SetKeyExpire(string key, string value, double expire)
        {
            var expireTime = TimeSpan.FromMinutes(expire);
            return await db.StringSetAsync(key, value, expireTime, false, StackExchange.Redis.When.Always);
        }

        //添加一个key 或者覆盖key的值
        public async Task<bool> SetKeyExpire(string key, object value, double expire)
        {
            var expireTime = TimeSpan.FromMinutes(expire);
            return await db.StringSetAsync(key, (RedisValue)value, expireTime, false, StackExchange.Redis.When.Always);
        }

        //只有在键不存在的时候才设置
        public async Task<bool> SetKeyNx(string key, string value)
        {
            return await db.StringSetAsync(key, value, null, false, When.NotExists);
        }

        //只有在键不存在的时候才设置
        public async Task<bool> SetKeyNxExpire(string key, string value, double expire)
        {
            var expireTime = TimeSpan.FromMinutes(expire);
            return await db.StringSetAsync(key, value, expireTime, false, When.NotExists);
        }
        //只有在键不存在的时候才设置
        public async Task<bool> SetKeyNxExpire(string key, object value, double expire)
        {
            var expireTime = TimeSpan.FromMinutes(expire);
            return await db.StringSetAsync(key, (RedisValue)value, expireTime, false, When.NotExists);
        }

        public async void Remove(string key)
        {
            db.KeyDelete(key);
        }

        /// <summary>
        /// 获取一个key的字符串
        /// </summary>
        public async Task<string> GetString(string key)
        {
            if (db == null)
            {
                return default;
            }
            var value = await db.StringGetAsync(key);
            if (value.IsNullOrEmpty)
            {
                return default;
            }
            return value.ToString();
        }

        /// <summary>
        /// 获取一个key的对象
        /// </summary>
        public async Task<T> GetStringKey<T>(string key)
        {
            if (db == null)
            {
                return default;
            }
            var value = await db.StringGetAsync(key);
            if (value.IsNullOrEmpty)
            {
                return default;
            }
            return JsonConvert.DeserializeObject<T>(value);
        }


        //getset一个key，获取旧值并设置新值
        public async Task<T> GetSetKey<T>(string key, string value)
        {
            var oldvalue = await db.StringGetSetAsync(key, value);

            return JsonConvert.DeserializeObject<T>(oldvalue);
        }


        //mset 一次设置多个数据
        public async Task<bool> MSET(KeyValuePair<RedisKey, RedisValue>[] values)
        {
            return await db.StringSetAsync(values, When.NotExists);
        }

        //mget 一次获取多个数据
        public async Task<Task<RedisValue[]>> MGET(RedisKey[] keys)
        {
            return db.StringGetAsync(keys);
        }


        //获取string的length

        public async Task<long> KeyLen(string key)
        {
            return await db.StringLengthAsync(key);
        }


        //append

        public async Task<long> Append(string key, string appendvalue)
        {
            return await db.StringAppendAsync(key, appendvalue);
        }

        //get range

        public async Task<RedisValue> GetRange(string key, int start, int end)
        {
            return await db.StringGetRangeAsync(key, start, end);
        }


        //增加
        public async Task<long> Incr(string key, int count)
        {
            return await db.StringIncrementAsync(key, count);
        }

        //减少
        public async Task<long> Decr(string key, int count)
        {
            return await db.StringDecrementAsync(key, count);
        }

    }

}